﻿//--------------------------------------------------------------------------------------
// File: ProjectFramework.cpp
//
// Starting point for new Direct3D 11 samples.  For a more basic starting point, 
// use the EmptyProject11 sample instead.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "DXUT.h"
#include "DXUTgui.h"
#include "DXUTmisc.h"
#include "DXUTCamera.h"
#include "DXUTSettingsDlg.h"
#include "SDKmisc.h"
#include "SDKmesh.h"
#include "resource.h"
#include "Utility\\GUIConsole.h"
#include "Utility\\DialogFileIO.h"
#include "Utility\\DirectoryUtil.h"
#include "Utility\\UtilityFunctions.h"
#include "Effects11\\Inc\\d3dx11effect.h"

#include "IO\\Collada\\ColladaRender.h"
#include "IO\\ObjFileLoader.h"
#include "IO\\XFileLoader.h"
#include "IO\\GonioFilesIO.h"
#include "IO\\PCGGonioFilesIO.h"

#include "RenderTech\\RenderTechFactory.h"
#include "RenderTech\\RenderTechType.h"
#include "RenderTech\\RenderStaticMesh.h"
#include "RenderTech\\RenderAssistLineShell.h"
#include "RenderTech\\RenderEMCubeMap.h"
#include "RenderTech\\RenderBRDFModels.h"

#include "Utility/GUI/WNDDialogLoadXYZ.h"
//#define DEBUG_VS   // Uncomment this line to debug D3D9 vertex shaders 
//#define DEBUG_PS   // Uncomment this line to debug D3D9 pixel shaders 

//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
CModelViewerCamera          g_Camera;               // A model viewing camera
CFirstPersonCamera          g_LCamera;              // A first person camera to control the light
CDXUTDialogResourceManager  g_DialogResourceManager; // manager for shared resources of dialogs
CD3DSettingsDlg             g_SettingsDlg;          // Device settings dialog
CDXUTTextHelper*            g_pTxtHelper = NULL;
CDXUTDialog                 g_HUD;                  // dialog for standard controls
CDXUTDialog                 g_SampleUI;             // dialog for sample specific controls

// Direct3D 9 resources
extern ID3DXFont*           g_pFont9;
extern ID3DXSprite*         g_pSprite9;

//Windows Dialog function
CDialogFileIO*				g_pDialogFileIO = NULL;
CDirectoryUtil*             g_pDirectoryUtil = NULL;

//Rendering related variables
CGrowableArray<RenderTechType> g_RenderTechArr;
int g_iCurrentRenderIdx = 0;
CObjFileLoader<VertexNormUV>* pObjLoader = NULL;

//controls
bool						g_bFullScreen = false;
int g_iY = 30;
int g_iYo = 26;
int g_iWidth = 140;
int g_iHeight = 18;
bool						g_bSaveFBimage = false;
float						g_fExpoParam = 1.0f;
float						g_fGammaParam  = 1.0f;
CDXUTComboBox*              g_ListEMFilesCombo = NULL;

CGonioFilesIO*              g_pGonioFile = NULL;
CPCGGonioFilesIO*           g_pPCGGonioFile = NULL;
//--------------------------------------------------------------------------------------
// GUI dialogs
//--------------------------------------------------------------------------------------
CWNDDialogLoadXYZ*           g_pDlgLoadXYZFile = NULL;
//--------------------------------------------------------------------------------------
// UI control IDs
//--------------------------------------------------------------------------------------
#include "UIControlsDef.h"


//--------------------------------------------------------------------------------------
// Forward declarations 
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
                          void* pUserContext );
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );

extern bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
                                             bool bWindowed, void* pUserContext );
extern HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice,
                                            const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
extern HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                           void* pUserContext );
extern void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime,
                                        void* pUserContext );
extern void CALLBACK OnD3D9LostDevice( void* pUserContext );
extern void CALLBACK OnD3D9DestroyDevice( void* pUserContext );

bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo,
                                       DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext );
HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc,
                                     void* pUserContext );
HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain,
                                         const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext );
void CALLBACK OnD3D11DestroyDevice( void* pUserContext );
void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime,
                                 float fElapsedTime, void* pUserContext );

void InitApp();
void RenderText();
void CreateRenderTechs();

//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing 
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
	//redirect io to console window
	RedirectIOToConsole();
	//User-defined Variables
	g_pDialogFileIO = new CDialogFileIO();
	g_pDirectoryUtil = new CDirectoryUtil();
	TCHAR Dir[MAX_PATH];
	GetCurrentDirectory(MAX_PATH, Dir);
	g_pDirectoryUtil->initSubDirectory(Dir);

	g_pDlgLoadXYZFile = new CWNDDialogLoadXYZ();
	g_pDlgLoadXYZFile->Create(MAKEINTRESOURCE(IDD_DIALOG_LOADXYZ));
	// DXUT will create and use the best device (either D3D9 or D3D11) 
    // that is available on the system depending on which D3D callbacks are set below

    // Set DXUT callbacks
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackKeyboard( OnKeyboard );
    DXUTSetCallbackFrameMove( OnFrameMove );
    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );

    DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
    DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
    DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );
    DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );
    DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
    DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );

    DXUTSetCallbackD3D11DeviceAcceptable( IsD3D11DeviceAcceptable );
    DXUTSetCallbackD3D11DeviceCreated( OnD3D11CreateDevice );
    DXUTSetCallbackD3D11SwapChainResized( OnD3D11ResizedSwapChain );
    DXUTSetCallbackD3D11SwapChainReleasing( OnD3D11ReleasingSwapChain );
    DXUTSetCallbackD3D11DeviceDestroyed( OnD3D11DestroyDevice );
    DXUTSetCallbackD3D11FrameRender( OnD3D11FrameRender );

    InitApp();
	DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
    DXUTSetCursorSettings( true, true );
    DXUTCreateWindow( L"ProjectFramework" );

	// Only require 10-level hardware, change to D3D_FEATURE_LEVEL_11_0 to require 11-class hardware
    // Switch to D3D_FEATURE_LEVEL_9_x for 10level9 hardware
    if(g_bFullScreen)
		DXUTCreateDevice( D3D_FEATURE_LEVEL_9_1, false, 1600, 1200 );
	else
		DXUTCreateDevice( D3D_FEATURE_LEVEL_9_1, true, 1680, 1050 );//do not exceed the screen resolution of 1900x1200
    DXUTMainLoop(); // Enter into the DXUT render loop
	
	// Delete User-define variables
	SAFE_DELETE(g_pDialogFileIO);
	SAFE_DELETE(g_pDirectoryUtil);
	SAFE_DELETE(g_pDlgLoadXYZFile);
    return DXUTGetExitCode();
}


//--------------------------------------------------------------------------------------
// Initialize the app 
//--------------------------------------------------------------------------------------
void InitApp()
{
    g_SettingsDlg.Init( &g_DialogResourceManager );
    g_HUD.Init( &g_DialogResourceManager );
    g_SampleUI.Init( &g_DialogResourceManager );

    g_HUD.SetCallback( OnGUIEvent );
	int iY = g_iY;
	int iYo = g_iYo;
	int iWidth = g_iWidth;
	int iHeight = g_iHeight;

    g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, iY, iWidth, iHeight );
    g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, iY += iYo, iWidth, iHeight, VK_F3 );
    g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, iY += iYo, iWidth, iHeight, VK_F2);
	g_HUD.AddButton(IDC_BASICUTILITYMENU,L"Basic Utility Menu (F4)",0,iY+=iYo,iWidth,iHeight,VK_F4);
    g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;
	//g_SampleUI.AddButton(IDC_BUTTON_GENNDFS,L"GenNDFS",0,iY+=iYo,iWidth,iHeight);
	g_SampleUI.AddButton(IDC_BUTTON_LOADXYZFILE,L"LoadXYZ",0,iY+=iYo,iWidth,iHeight);
	g_SampleUI.AddButton(IDC_BUTTON_GENSINGLENDF,L"Gen1NDF",0,iY+=iYo,iWidth,iHeight);
	g_SampleUI.AddButton(IDC_BUTTON_GEN1DPLOTNDF,L"Gen1DPlot",0,iY+=iYo,iWidth,iHeight);
	g_SampleUI.AddButton(IDC_BUTTON_SAVEFB,L"SaveFB",0,iY+=iYo,iWidth,iHeight);
	
	TCHAR tmpStr[MAX_PATH];
	memset(tmpStr,0,sizeof(TCHAR)*MAX_PATH);
	swprintf(tmpStr,L"fExpo = %.2f",g_fExpoParam);
	g_SampleUI.AddStatic(IDC_STATIC_FEXPO,tmpStr,0,iY+=iYo,iWidth,iHeight);
	g_SampleUI.AddSlider(IDC_SLIDER_FEXPO,0,iY+=iYo,iWidth,iHeight,0,60,30);
	memset(tmpStr,0,sizeof(TCHAR)*MAX_PATH);
	swprintf(tmpStr,L"Gamma = %.2f",g_fGammaParam);
	g_SampleUI.AddStatic(IDC_STATIC_GAMMA,tmpStr,0,iY+=iYo,iWidth,iHeight);
	g_SampleUI.AddSlider(IDC_SLIDER_GAMMA,0,iY+=iYo,iWidth,iHeight,1,300,100);

	//list all EM Files
	TCHAR* strEMFolder = new TCHAR[MAX_PATH];
	memset(strEMFolder,0,sizeof(TCHAR)*MAX_PATH);
	wcscpy(strEMFolder, g_pDirectoryUtil->m_strWorkDirectory);
	wcscat(strEMFolder, L"\\Models\\EM");
	CGrowableArray<std::wstring> EMFilesNameArr;
	UtilityFunction::ListAllFilesInFolder(strEMFolder,L"*.dds", EMFilesNameArr);
	g_SampleUI.AddComboBox(IDC_COMBOBOX_LISTEM,0,iY+=iYo,iWidth+20,iHeight,0,false,&g_ListEMFilesCombo);
	if( g_ListEMFilesCombo && EMFilesNameArr.GetSize()>0)
	{
		g_ListEMFilesCombo->SetDropHeight( 64 );
		for (unsigned int i = 0; i < EMFilesNameArr.GetSize(); i++)
		{
			g_ListEMFilesCombo->AddItem(EMFilesNameArr[i].data(),NULL);
		}
		g_ListEMFilesCombo->SetSelectedByIndex( 0 );
	}
	SAFE_DELETE_ARRAY(strEMFolder);
	//return Y value
	g_iY = iY;	
}
//--------------------------------------------------------------------------------------
// Initialize the app 
//--------------------------------------------------------------------------------------
void GenerateSingleNDF(ID3D11Device* pd3dDevice, int NDFDim, CXYZFileIO* pXYZFile, char* strOutputFileName)
{
	printf("starting generate ndf image:...");
	{
		char strFileName[MAX_PATH];
		ZeroMemory(strFileName,sizeof(char)*MAX_PATH);
		std::vector<D3DXVECTOR3> tmpNormal;
		for (unsigned int i = 0 ; i < pXYZFile->m_arrNormalAreaWeighted.size(); i++)
		{
			tmpNormal.push_back(pXYZFile->m_arrNormalAreaWeighted[i].Normal);
		}

		sprintf(strFileName,strOutputFileName);
		std::string strNDFName;
		strNDFName.assign(strFileName);
		std::wstring wstrNDFName = UtilityFunction::strtowstr(strNDFName);

		CD3DUtilityFunction::SaveNDFImage(pd3dDevice,(WCHAR*)wstrNDFName.data(),NDFDim,NDFDim,tmpNormal.data(),
			tmpNormal.size(),1.0f);

		printf("*");
	}
	printf("finishing generate ndf image:...");
}

void GenerateAllNDFs(ID3D11Device* pd3dDevice, int NDFDim)
{
	CXYZFileIO* pXYZFile = new CXYZFileIO();

	printf("starting generate ndf image:...");
	for (int i = 0; i<100; i++)
	{
		char strFileName[MAX_PATH];
		ZeroMemory(strFileName,sizeof(char)*MAX_PATH);
		sprintf(strFileName,"OrgData/zygodata_May7th/MyData%03d.xyz", i);
		//load xyz file;
		pXYZFile->LoadFromFile(strFileName,350,260);
		pXYZFile->EstimateNormalAreaWeighted_IgnoreNoDataPt();
		std::vector<D3DXVECTOR3> tmpNormal;
		for (unsigned int i = 0 ; i < pXYZFile->m_arrNormalAreaWeighted.size(); i++)
		{
			tmpNormal.push_back(pXYZFile->m_arrNormalAreaWeighted[i].Normal);
		}

		ZeroMemory(strFileName,sizeof(char)*MAX_PATH);
		sprintf(strFileName,"output/zygodata_May7th/ndf%03d.bmp", i);
		std::string strNDFName;
		strNDFName.assign(strFileName);
		std::wstring wstrNDFName = UtilityFunction::strtowstr(strNDFName);
				
		CD3DUtilityFunction::SaveNDFImage(pd3dDevice,(WCHAR*)wstrNDFName.data(),NDFDim,NDFDim,tmpNormal.data(),
			tmpNormal.size(),1.0f);

		printf("*");
	}
	printf("finishing generate ndf image:...");

	SAFE_DELETE(pXYZFile);
}
void CreateRenderTechs(CDirectoryUtil* pDirectoryUtil, ID3D11Device* pd3dDevice)
{
	//(1) New Tech + put into array firstly
	//(2) then load the model or data afterwards
	//create new render technique
	g_RenderTechArr.Add(RenderTechType(TRENDERHEIGHTMAP));
	CRenderHeightMap* pHMTech = static_cast<CRenderHeightMap*>((g_RenderTechArr[g_RenderTechArr.GetSize()-1]).m_pTech);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May7th/pattern3.xyz");
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May7th/MyData014.xyz",350,260);

	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May9th/stitch15x3_1_Mod7.xyz", 4770, 740);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May9th/stitch4x4_1_Mod7.xyz", 1300, 970);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May9th/stitch5x5_1_Mod4.xyz", 1610, 1210);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May9th/stitch6x6_1_Mod4.xyz", 1930, 1450);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May9th/stitch2x2_5_Mod4.xyz", 670, 500);
	
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May11th/stitch_4x4_1_Mod4.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May11th/stitch_4x4_2_Mod4.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May11th/stitch_4x4_3_Mod4.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May11th/stitch_4x4_4_Mod4.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May11th/stitch_4x4_5_Mod4.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May11th/stitch_8x8_1_Mod4.xyz", 5160, 3870);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May11th/stitch_15x3_1_Mod4.xyz", 9610, 1480);

	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan01_20X2XMod4.xyz", 180, 130);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan02_20X2XMod4.xyz", 180, 130);
    //pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan03_20X2XMod4.xyz", 180, 130);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan04_20X2XMod4.xyz", 180, 130);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan01_50X1XMod4.xyz", 140, 110);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan02_50X1XMod4.xyz", 140, 110);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan03_50X1XMod4.xyz", 140, 110);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan04_50X1XMod4.xyz", 140, 110);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/SingleScan05_50X1XMod4.xyz", 140, 110);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/stitch01_2x2_50X1XMod4.xyz", 270, 200);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/stitch01_4x4_50X1XMod4.xyz", 520, 390);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/stitch01_8x8_50X1XMod4.xyz", 1020, 770);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_May16th/stitch01_15x4_50X1XMod4.xyz", 1910, 390);

	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Data01_20x_0.5xzoom.xyz", 710, 530);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Data01_20x_1xzoom.xyz", 350, 260);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Data01_20x_2xzoom.xyz", 180, 130);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Data01_50x_0.5xzoom.xyz", 280, 210);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Data01_50x_1xzoom.xyz", 140, 110);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Data01_50x_2xzoom.xyz", 70, 50);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich_4x4_20x_0.5xzoom.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich_4x4_20x_1xzoom.xyz", 1300, 970);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich_4x4_20x_2xzoom.xyz", 650, 490);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich_4x4_50x_0.5xzoom.xyz", 1050, 780);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich_4x4_50x_1xzoom.xyz", 520, 390);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich_4x4_50x_2xzoom.xyz", 260, 200);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich02_4x4_20x_0.5xzoom.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich02_4x4_20x_1xzoom.xyz", 1300, 970);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich02_4x4_20x_2xzoom.xyz", 650, 490);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich02_4x4_50x_0.5xzoom.xyz", 1050, 780);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich02_4x4_50x_1xzoom.xyz", 520, 390);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June18th/Stich02_4x4_50x_2xzoom.xyz", 260, 200);

	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Data01_20x_0.5xzoom.xyz", 710, 530);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Data01_20x_1xzoom.xyz", 350, 260);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Data01_20x_2xzoom.xyz", 180, 130);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Data01_50x_0.5xzoom.xyz", 280, 210);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Data01_50x_1xzoom.xyz", 140, 110);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Data01_50x_2xzoom.xyz", 70, 50);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_2x2_20x_0.5xzoom.xyz", 1340, 1010);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_2x2_20x_1xzoom.xyz", 670, 500);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_2x2_20x_2xzoom.xyz", 340, 250);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_2x2_50x_0.5xzoom.xyz", 540, 400);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_2x2_50x_1xzoom.xyz", 270, 200);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_2x2_50x_2xzoom.xyz", 130, 100);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_4x4_20x_0.5xzoom.xyz", 2620, 1960);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_4x4_20x_1xzoom.xyz", 1300, 970);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_4x4_20x_2xzoom.xyz", 650, 490);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_4x4_50x_0.5xzoom.xyz", 1050, 780);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_4x4_50x_1xzoom.xyz", 520, 390);
	//pHMTech->LoadXYZFile(pDirectoryUtil, SUBDIRECTORY::ORGDATADIR, L"zygodata_June19th/Stitch_4x4_50x_2xzoom.xyz", 260, 200);

	//(1.0/(pi*(a^2)*(cos(degtorad(x))^4)))*(exp(-(tan(degtorad(x))^2)/(a^2)))
	//b*((pi*(a^2)*(cos(x)^4)))^(-1)*exp(-(tan(x)^2)/(a^2))  //Beckmann
	//b*((a^2)*((pi*(cos(x)^4)*((a^2+tan(x)^2)^2))^(-1)))  //GGX
	//ZeroMemory(g_strLoadedXYZFileName,sizeof(char)*MAX_PATH);
	//sprintf_s(g_strLoadedXYZFileName,"Data01_50x_0.5xzoom");	
	g_iCurrentRenderIdx = 0;
	/*
	g_RenderTechArr.Add(RenderTechType(TRENDERSTATICMESH));
	CRenderStaticMesh* pSMTech = static_cast<CRenderStaticMesh*>((g_RenderTechArr[g_RenderTechArr.GetSize()-1]).m_pTech);
	pSMTech->m_pModelRender = new ColladaRender<VertexNormUVTang,VertexNorm>();
	char strFileName[MAX_PATH];
	CD3DUtilityFunction::CreateFileName(strFileName,MAX_PATH,pDirectoryUtil,SUBDIRECTORY::MODELDIR, L"StaticExample.dae");
	if(!(pSMTech->m_pModelRender->LoadModel(strFileName, pd3dDevice)))
	{
	#ifdef _DEBUG
	OUTPUTERRORINFO;
	#endif
			return;
	}
	*/
	//g_RenderTechArr.Add(RenderTechType(TRENDERASSISTLINESHELL));
	
	g_RenderTechArr.Add(RenderTechType(TRENDERBRDFMODELS));	
	CRenderBRDFModels* pRenderBRDFTech = static_cast<CRenderBRDFModels*>((g_RenderTechArr[g_RenderTechArr.GetSize()-1]).m_pTech);
	//Load Model
	pRenderBRDFTech->m_pModelRender = new CObjFileLoader<VertexNormUV>();
	CMeshRender* pCurModelRender = pRenderBRDFTech->m_pModelRender;	
	if(pCurModelRender->bLocalCoordsSupport())
		pCurModelRender->NeedLocalCoords(true);
	pCurModelRender->LoadModel("Models\\athena.obj",pd3dDevice);
	//pCurModelRender->LoadModel("Models\\sphere.obj",pd3dDevice);
	//pCurModelRender->LoadModel("Models\\teapot.obj",pd3dDevice);
	//initEM
	DXUTComboBoxItem*pItem = g_ListEMFilesCombo->GetSelectedItem();
	pRenderBRDFTech->InitEMLighting(pItem->strText);
	
	int iY = g_iY;
	g_RenderTechArr[g_iCurrentRenderIdx].m_pTech->AddGUIComp(&g_HUD,&g_SampleUI,0,iY,g_iYo,g_iWidth,g_iHeight);
	//debug assist line
	/*int iVertNum = static_cast<CObjFileLoader<VertexNormUV>*>(pCurModelRender)->m_Vertices_Local.size();
	std::vector<VertexNormUVTang>& VertArr = static_cast<CObjFileLoader<VertexNormUV>*>(pCurModelRender)->m_Vertices_Local;
	CGrowableArray<PT_VertColor>& LineVertsArr = pRenderBRDFTech->m_pRenderAssistLine->m_ptArray;
	LineVertsArr.RemoveAll();
	for (unsigned int i = 0; i < iVertNum; i++)
	{
	if (i%200 == 0)
	{
	PT_VertColor vert1;
	vert1.pos = VertArr[i].Position;
	vert1.color = D3DXVECTOR4(1,0,0,1);
	LineVertsArr.Add(vert1);

	PT_VertColor vert2;
	vert2.pos = vert1.pos + VertArr[i].Normal;
	vert2.color = D3DXVECTOR4(1,0,0,1);
	LineVertsArr.Add(vert2);

	PT_VertColor vert3;
	vert3.pos = VertArr[i].Position;
	vert3.color = D3DXVECTOR4(0,1,0,1);
	LineVertsArr.Add(vert3);

	PT_VertColor vert4;
	vert4.pos = vert3.pos + VertArr[i].Tangent;
	vert4.color = D3DXVECTOR4(0,1,0,1);
	LineVertsArr.Add(vert4);

	PT_VertColor vert5;
	vert5.pos = VertArr[i].Position;
	vert5.color = D3DXVECTOR4(0,0,1,1);
	LineVertsArr.Add(vert5);

	PT_VertColor vert6;
	vert6.pos = vert5.pos + VertArr[i].BiNormal;
	vert6.color = D3DXVECTOR4(0,0,1,1);
	LineVertsArr.Add(vert6);

	}
	}
	if(LineVertsArr.GetSize() > 0)
	pRenderBRDFTech->m_pRenderAssistLine->m_bPtsReady = true;*/
	

	/*//pObjLoader->LoadModel("Models\\cup.obj",pd3dDevice);
#define XFILE
#ifdef XFILE
	pSMTech->m_pModelRender = new CXFileLoader<VertexNormUV>;
	char strFileName[MAX_PATH];
	CD3DUtilityFunction::CreateFileName(strFileName,MAX_PATH,pDirectoryUtil,SUBDIRECTORY::MODELDIR, L"tiger.x");
#else
	pSMTech->m_pModelRender = new CObjFileLoader<VertexNormUV>;
	char strFileName[MAX_PATH];
	CD3DUtilityFunction::CreateFileName(strFileName,MAX_PATH,pDirectoryUtil,SUBDIRECTORY::MODELDIR, L"cup.obj");
#endif
	if(!pSMTech->m_pModelRender->LoadModel(strFileName,pd3dDevice))
	{
	#ifdef _DEBUG
	OUTPUTERRORINFO;
	#endif
			return;
	}
	else
		printf("%s model is loaded!\n", strFileName);

	g_iCurrentRenderIdx = g_RenderTechArr.GetSize()-1;*/
}
//--------------------------------------------------------------------------------------
// Render the help and statistics text. This function uses the ID3DXFont interface for 
// efficient text rendering.
//--------------------------------------------------------------------------------------
void RenderText()
{
    g_pTxtHelper->Begin();
    g_pTxtHelper->SetInsertionPos( 5, 5 );
    g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
    g_pTxtHelper->DrawTextLine( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) );
    g_pTxtHelper->DrawTextLine( DXUTGetDeviceStats() );
    g_pTxtHelper->End();
}


//--------------------------------------------------------------------------------------
// Reject any D3D11 devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo,
                                       DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3D11 resources that aren't dependant on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc,
                                     void* pUserContext )
{
    HRESULT hr;
	ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext();
    V_RETURN( g_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) );
    V_RETURN( g_SettingsDlg.OnD3D11CreateDevice( pd3dDevice ) );
    g_pTxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &g_DialogResourceManager, 15 );

	//g_pGonioFile = new CGonioFilesIO();
	//g_pGonioFile->ReadAngleMappingFile("OrgData\\Gonio_RIT\\AngleMapping.csv");
	////g_pGonioFile->ReadOrgGonioMeasuredData("OrgData\\Gonio_RIT\\CornellSteel_flop_0.Csv");
	//g_pGonioFile->ReadOrgGonioMeasuredData("OrgData\\Gonio_RIT\\CornellSteel_90deg_flop_0.Csv",false,90);
	//g_pGonioFile->ComputeNDFInverse(pd3dDevice,L"Output\\NDF_rit.bmp","Output\\1DPlot.txt",256,256);
	//SAFE_DELETE(g_pGonioFile);

	g_pPCGGonioFile = new CPCGGonioFilesIO();
	//g_pPCGGonioFile->ReadGonioFile("OrgData\\Gonio_PCG\\Stainless\\MajorAxis\\NormalDisBand550.txt",550);
	g_pPCGGonioFile->ReadGonioFile("OrgData\\Gonio_PCG\\Stainless2\\brushed\\major\\Brushed_Major_550nm.txt",550);
	g_pPCGGonioFile->ComputeNDFInverse(pd3dDevice,L"Output\\Stainless2\\brushed\\NDF_major.bmp","Output\\Stainless2\\brushed\\1DPlot_Major.txt",256,256);
	g_pPCGGonioFile->ReadGonioFile("OrgData\\Gonio_PCG\\Stainless2\\brushed\\minor\\Brushed_Minor_550nm.txt",550);
	g_pPCGGonioFile->ComputeNDFInverse(pd3dDevice,L"Output\\Stainless2\\brushed\\NDF_minor.bmp","Output\\Stainless2\\brushed\\1DPlot_Minor.txt",256,256);
	g_pPCGGonioFile->ReadGonioFile("OrgData\\Gonio_PCG\\Stainless2\\mirror\\major\\Mirror_Major_550nm.txt",550);
	g_pPCGGonioFile->ComputeNDFInverse(pd3dDevice,L"Output\\Stainless2\\mirror\\NDF_major.bmp","Output\\Stainless2\\mirror\\1DPlot_Major.txt",256,256);
	g_pPCGGonioFile->ReadGonioFile("OrgData\\Gonio_PCG\\Stainless2\\mirror\\minor\\Mirror_Minor_550nm.txt",550);
	g_pPCGGonioFile->ComputeNDFInverse(pd3dDevice,L"Output\\Stainless2\\mirror\\NDF_minor.bmp","Output\\Stainless2\\mirror\\1DPlot_Minor.txt",256,256);
	printf("PCG Gonio Output Generated!\n");
	SAFE_DELETE(g_pPCGGonioFile);
	
	//Create render techs
	CreateRenderTechs(g_pDirectoryUtil, pd3dDevice);
    // Create render resources here
	for(int idx = 0; idx < g_RenderTechArr.GetSize(); idx++)
		g_RenderTechArr[idx].m_pTech->OnD3D11CreateDevice(pd3dDevice, pBackBufferSurfaceDesc, g_pDirectoryUtil, pUserContext);

    // Setup the camera's view parameters
    D3DXVECTOR3 vecEye( 0.0f, 0.0f, -1.0f );
    D3DXVECTOR3 vecAt ( 0.0f, 0.0f, -0.0f );
	g_Camera.SetViewParams( &vecEye, &vecAt );

	return S_OK;
}


//--------------------------------------------------------------------------------------
// Create any D3D11 resources that depend on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain,
                                         const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
    HRESULT hr;

    V_RETURN( g_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
    V_RETURN( g_SettingsDlg.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );

    // Setup the camera's projection parameters
    float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
    g_Camera.SetProjParams( D3DX_PI / 4, fAspectRatio, 0.001f, 10000.0f );
    g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
    g_Camera.SetButtonMasks( MOUSE_LEFT_BUTTON, MOUSE_WHEEL, MOUSE_MIDDLE_BUTTON );

    g_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 );
    g_HUD.SetSize( 170, 170 );
    //g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 500 );
	g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 800 );
    g_SampleUI.SetSize( 170, 800 );
	
	// refresh render sources here
	for(int idx = 0; idx < g_RenderTechArr.GetSize(); idx++)
		g_RenderTechArr[idx].m_pTech->OnD3D11ResizedSwapChain(pd3dDevice,pSwapChain, pBackBufferSurfaceDesc, g_pDirectoryUtil, pUserContext);

	return S_OK;
}


//--------------------------------------------------------------------------------------
// Render the scene using the D3D11 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime,
                                 float fElapsedTime, void* pUserContext )
{
    // If the settings dialog is being shown, then render it instead of rendering the app's scene
    if( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.OnRender( fElapsedTime );
        return;
    }       

    //float ClearColor[4] = { 0.176f, 0.196f, 0.667f, 0.0f };
	//float ClearColor[4] = { 0.0f, 112.0f/255, 192.0f/255, 1.0f };
	float ClearColor[4] = { 0.0f, 0.16364f, 0.53564f, 1.0f }; //gamma correction x^2.2
	//float ClearColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; //gamma correction x^2.2
    ID3D11RenderTargetView* pRTV = DXUTGetD3D11RenderTargetView();
    pd3dImmediateContext->ClearRenderTargetView( pRTV, ClearColor );

    // Clear the depth stencil
    ID3D11DepthStencilView* pDSV = DXUTGetD3D11DepthStencilView();
    pd3dImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0, 0 );

	// Render objects here...
	g_RenderTechArr[g_iCurrentRenderIdx].m_pTech->OnD3D11FrameRender(pd3dDevice,pd3dImmediateContext,&g_Camera, g_pDirectoryUtil,fTime,fElapsedTime,pUserContext);	

	///////////////////////////////
	DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
	if(g_bSaveFBimage)
	{
		//CD3DUtilityFunction::SaveFrameBufferToFile(pd3dImmediateContext,L"Output\\FB.png", D3DX11_IFF_PNG);
		CD3DUtilityFunction::SaveFrameBufferToFile(pd3dImmediateContext,L"Output/zygodata_June19th/FB.png", D3DX11_IFF_PNG);
		g_bSaveFBimage = false;
	}
    g_HUD.OnRender( fElapsedTime );
    g_SampleUI.OnRender( fElapsedTime );
    RenderText();
    DXUT_EndPerfEvent();

    static DWORD dwTimefirst = GetTickCount();
    if ( GetTickCount() - dwTimefirst > 5000 )
    {    
        OutputDebugString( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) );
        OutputDebugString( L"\n" );
        dwTimefirst = GetTickCount();
    }
}


//--------------------------------------------------------------------------------------
// Release D3D11 resources created in OnD3D11ResizedSwapChain 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext )
{
    g_DialogResourceManager.OnD3D11ReleasingSwapChain();

	for(int idx = 0; idx < g_RenderTechArr.GetSize(); idx++)	
		g_RenderTechArr[idx].m_pTech->OnD3D11ReleasingSwapChain(pUserContext);
}


//--------------------------------------------------------------------------------------
// Release D3D11 resources created in OnD3D11CreateDevice 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D11DestroyDevice( void* pUserContext )
{
    g_DialogResourceManager.OnD3D11DestroyDevice();
    g_SettingsDlg.OnD3D11DestroyDevice();
    DXUTGetGlobalResourceCache().OnDestroyDevice();
    SAFE_DELETE( g_pTxtHelper );

    // Delete all the render technique;
	for(int idx = 0; idx < g_RenderTechArr.GetSize(); idx++)
		g_RenderTechArr[idx].m_pTech->OnD3D11DestroyDevice(pUserContext);
	g_RenderTechArr.RemoveAll();



}


//--------------------------------------------------------------------------------------
// Called right before creating a D3D9 or D3D11 device, allowing the app to modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
    if( pDeviceSettings->ver == DXUT_D3D9_DEVICE )
    {
        IDirect3D9* pD3D = DXUTGetD3D9Object();
        D3DCAPS9 Caps;
        pD3D->GetDeviceCaps( pDeviceSettings->d3d9.AdapterOrdinal, pDeviceSettings->d3d9.DeviceType, &Caps );

        // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
        // then switch to SWVP.
        if( ( Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == 0 ||
            Caps.VertexShaderVersion < D3DVS_VERSION( 1, 1 ) )
        {
            pDeviceSettings->d3d9.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
        }

        // Debugging vertex shaders requires either REF or software vertex processing 
        // and debugging pixel shaders requires REF.  
#ifdef DEBUG_VS
        if( pDeviceSettings->d3d9.DeviceType != D3DDEVTYPE_REF )
        {
            pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
            pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
            pDeviceSettings->d3d9.BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
        }
#endif
#ifdef DEBUG_PS
        pDeviceSettings->d3d9.DeviceType = D3DDEVTYPE_REF;
#endif
    }

    // For the first device created if its a REF device, optionally display a warning dialog box
    static bool s_bFirstTime = true;
    if( s_bFirstTime )
    {
        s_bFirstTime = false;
        if( ( DXUT_D3D9_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF ) ||
            ( DXUT_D3D11_DEVICE == pDeviceSettings->ver &&
            pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) )
        {
            DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver );
        }

    }

    return true;
}


//--------------------------------------------------------------------------------------
// Handle updates to the scene.  This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
    // Update the camera's position based on user input 
    g_Camera.FrameMove( fElapsedTime );
}


//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
                          void* pUserContext )
{
    // Pass messages to dialog resource manager calls so GUI state is updated correctly
    *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass messages to settings dialog if its active
    if( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
        return 0;
    }

    // Give the dialogs a chance to handle the message first
    *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;
    *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass all remaining windows messages to camera so it can respond to user input
    g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );

    return 0;
}


//--------------------------------------------------------------------------------------
// Handle key presses
//--------------------------------------------------------------------------------------
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
	ID3D11Device* pd3dDevice = DXUTGetD3D11Device();
	if( bKeyDown )
    {
        switch( nChar )
        {
            case VK_F12:
				{
					g_RenderTechArr[g_iCurrentRenderIdx].m_pTech->ReloadEffectsDebug(pd3dDevice, g_pDirectoryUtil);
					printf("shader reloaded!\n");
				}
				break;
        }
    }
}


//--------------------------------------------------------------------------------------
// Handles the GUI events
//--------------------------------------------------------------------------------------
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext )
{
    switch( nControlID )
    {
        case IDC_TOGGLEFULLSCREEN:
            DXUTToggleFullScreen();
            break;
        case IDC_TOGGLEREF:
            DXUTToggleREF();
            break;
        case IDC_CHANGEDEVICE:
            g_SettingsDlg.SetActive( !g_SettingsDlg.IsActive() );
            break;
		case IDC_BASICUTILITYMENU:
			g_pDialogFileIO->BasicUtilityMenu();
			break;
		case IDC_BUTTON_SAVEFB:
			g_bSaveFBimage = true;
			break;
		case IDC_BUTTON_GENNDFS:
			{
				ID3D11Device* pd3dDevice = DXUTGetD3D11Device();
				//Create NDFs
				GenerateAllNDFs(pd3dDevice, 512);
			}
			break;
		case IDC_BUTTON_LOADXYZFILE:
			{
				g_pDlgLoadXYZFile->ShowDialog(MAKEINTRESOURCE(IDD_DIALOG_LOADXYZ));
				CRenderHeightMap* pHMTech = static_cast<CRenderHeightMap*>((g_RenderTechArr[0]).m_pTech);
				g_pDlgLoadXYZFile->SetCurRenderHMTech(pHMTech);
			}
			break;
		case IDC_BUTTON_GEN1DPLOTNDF:
			{
				printf("starting generate 1D Plot Data:...");
				{
					std::vector<D3DXVECTOR3> tmpNormal;
					CRenderHeightMap* pHMTech = static_cast<CRenderHeightMap*>((g_RenderTechArr[0]).m_pTech);
					for (unsigned int i = 0 ; i < pHMTech->GetXYZFile()->m_arrNormalAreaWeighted.size(); i++)
					{
						tmpNormal.push_back(pHMTech->GetXYZFile()->m_arrNormalAreaWeighted[i].Normal);
					}

					char strLoadedXYZFilePathName[MAX_PATH];
					ZeroMemory(strLoadedXYZFilePathName,sizeof(char)*MAX_PATH);
					strcpy_s(strLoadedXYZFilePathName,pHMTech->GetXYZFile()->GetStrXYZFilePathName());
					char* pPos = strrchr(strLoadedXYZFilePathName,'/');
					if(pPos==NULL)
						pPos = strrchr(strLoadedXYZFilePathName,'\\');
					char strLoadedXYZFileName[MAX_PATH];
					ZeroMemory(strLoadedXYZFileName,sizeof(char)*MAX_PATH);
					strcpy_s(strLoadedXYZFileName,(pPos+1));
					pPos = strrchr(strLoadedXYZFileName,'.');
					*pPos = 0;

					char strFileName[MAX_PATH];
					ZeroMemory(strFileName,sizeof(char)*MAX_PATH);
					sprintf_s(strFileName,"Output/1DPlotData/");
					strcat_s(strFileName,strLoadedXYZFileName);
					strcat_s(strFileName,"_1DPlot_x.txt");
					CD3DUtilityFunction::Save1DPlotData(strFileName,tmpNormal.data(),tmpNormal.size(),true);
					
					ZeroMemory(strFileName,sizeof(char)*MAX_PATH);
					sprintf_s(strFileName,"Output/1DPlotData/");
					strcat_s(strFileName,strLoadedXYZFileName);
					strcat_s(strFileName,"_1DPlot_y.txt");
					CD3DUtilityFunction::Save1DPlotData(strFileName,tmpNormal.data(),tmpNormal.size(),false);
					printf("*");
					tmpNormal.clear();
				}
				printf("finishing generate 1D Plot Data:...");
				
			}
			break;
		case IDC_BUTTON_GENSINGLENDF:
			{
				ID3D11Device* pd3dDevice = DXUTGetD3D11Device();
				//Create NDF
				CRenderHeightMap* pHMTech = static_cast<CRenderHeightMap*>((g_RenderTechArr[0]).m_pTech);
				//GenerateSingleNDF(pd3dDevice,1024,pHMTech->GetXYZFile(),"Output/zygodata_May9th/ndf.bmp");
				//GenerateSingleNDF(pd3dDevice,1024,pHMTech->GetXYZFile(),"Output/zygodata_May11th/ndf.bmp");
				//GenerateSingleNDF(pd3dDevice,1024,pHMTech->GetXYZFile(),"Output/zygodata_May16th/ndf.bmp");
				//GenerateSingleNDF(pd3dDevice,1024,pHMTech->GetXYZFile(),"Output/zygodata_June18th/ndf.bmp");
				//GenerateSingleNDF(pd3dDevice,1024,pHMTech->GetXYZFile(),"Output/zygodata_June19th/ndf.bmp");
				GenerateSingleNDF(pd3dDevice,256,pHMTech->GetXYZFile(),"Output/zygodata_June19th/ndf.bmp");
			}
			break;
		case IDC_SLIDER_FEXPO:
			{
				float fVal = g_SampleUI.GetSlider(IDC_SLIDER_FEXPO)->GetValue();
				fVal = (fVal-30)/10.0f;
				g_fExpoParam = powf(10.f,fVal);

				TCHAR tmpStr[MAX_PATH];
				memset(tmpStr,0,sizeof(TCHAR)*MAX_PATH);
				swprintf(tmpStr,L"fExpo = %.2f",g_fExpoParam);
				g_SampleUI.GetStatic(IDC_STATIC_FEXPO)->SetText(tmpStr);
			}
			break;

		case IDC_SLIDER_GAMMA:
			{
				float fVal = g_SampleUI.GetSlider(IDC_SLIDER_GAMMA)->GetValue();
				fVal = fVal/100.0f;
				g_fGammaParam = 1.0f/fVal;

				TCHAR tmpStr[MAX_PATH];
				memset(tmpStr,0,sizeof(TCHAR)*MAX_PATH);
				swprintf(tmpStr,L"Gamma = %.2f",g_fGammaParam);
				g_SampleUI.GetStatic(IDC_STATIC_GAMMA)->SetText(tmpStr);
			}
			break;
		case IDC_COMBOBOX_LISTEM:
			{
				DXUTComboBoxItem* pItem = g_SampleUI.GetComboBox(IDC_COMBOBOX_LISTEM)->GetSelectedItem();
				CRenderBRDFModels* pRenderBRDFTech = static_cast<CRenderBRDFModels*>((g_RenderTechArr[g_RenderTechArr.GetSize()-1]).m_pTech);
				ID3D11Device* pd3dDevice = DXUTGetD3D11Device();
				pRenderBRDFTech->m_pEMLighting->ChangeEMFile(pItem->strText,pd3dDevice,g_pDirectoryUtil);
			}
			break;			
    }

	//UI processed by current render technique
	g_RenderTechArr[g_iCurrentRenderIdx].m_pTech->OnGUIEvent(nEvent,nControlID,pControl,pUserContext);
}


